import 'package:analyzer/dart/element/element.dart' as ele;
import 'package:source_gen/source_gen.dart';
import 'package:build/build.dart';
import 'package:xanno/src/anno/utils/log.dart';
import 'dart:io';
import 'project.dart';
import 'tpl/tpl.dart' as tpl;

class ProjectGenerator extends GeneratorForAnnotation<GProject> {
  final separator = Platform.pathSeparator;
  final libs = [
    LibInfo(name: 'flutter_localizations', sdk: true),
    // LibInfo(name: 'flutter_cupertino_localizations', version: '1.0.1'),
    // LibInfo(name: 'observable_builder', version: '0.0.3'),
    LibInfo(name: 'flutter_slidable', version: '2.0.0'),
    LibInfo(name: 'path_parsing', version: '1.0.1'),
    LibInfo(name: 'lottie', version: '2.2.0'),
    LibInfo(name: 'redux', version: '5.0.0'),
    LibInfo(name: 'encrypt', version: '5.0.1'),
    LibInfo(name: 'flutter_redux', version: '0.10.0'),
    LibInfo(name: 'redux_persist_flutter', version: '0.9.0'),
    LibInfo(name: 'dio', version: '5.0.1'),
    LibInfo(name: 'package_info_plus', version: '3.0.3'),
    LibInfo(name: 'device_info_plus', version: '8.1.0'),
    LibInfo(name: 'connectivity_plus', version: '3.0.3'),
    LibInfo(name: 'path_provider', version: '2.0.13'),
    LibInfo(name: 'http_parser', version: '4.0.2'),
    LibInfo(name: 'intl', version: '0.17.0'),
    LibInfo(name: 'logging', version: '1.1.1'),
    LibInfo(name: 'redux_persist', version: '0.9.0'),
    LibInfo(name: 'shared_preferences', version: '2.0.18'),
    LibInfo(name: 'crypto', version: '3.0.2'),
    LibInfo(name: 'pointycastle', version: '3.6.2'),
  ];

  String readPubspec(String path) {
    var sb = StringBuffer();
    bool isDev = false;
    try {
      List<String> lines = File(path).readAsLinesSync();
      lines.forEach((line) {
        if (line.startsWith('dependencies:')) {
          isDev = false;
        }
        if (line.startsWith('dev_dependencies:')) {
          isDev = true;
        }
        // line = line.replaceAll(RegExp(r'(?<=\>\=).*?(?=\s+\<)'), '2.12.0');
        if (!isDev && line.startsWith('  flutter:')) {
          libs.forEach((lib) {
            if (lib.version != null) {
              sb.writeln('''  ${lib.name}: ^${lib.version}''');
            }
            if (lib.sdk) {
              sb.writeln('''  ${lib.name}:''');
              sb.writeln('''    sdk: flutter''');
            }
          });
        }
        sb.writeln(line);
      });
      sb.writeln('''flutter_intl:''');
      sb.writeln('''  enabled: true''');
      sb.writeln('''  class_name: S''');
      sb.writeln('''  main_locale: zh''');
      sb.writeln('''  arb_dir: lib/l10n''');
      sb.writeln('''  output_dir: lib/l10n/generated''');
      return sb.toString();
    } catch (e) {
      logPrint('文件读取失败! $e', level: Level.error);
    }
    return sb.toString();
  }

  @override
  generateForAnnotatedElement(
      ele.Element element, ConstantReader annotation, BuildStep buildStep) {
    // logPrint('start project', level: Level.info);
    var enable = false;
    try {
      enable = annotation.read('enable').boolValue;
    } catch (e) {}
    if (!enable) return null;
    var package = buildStep.inputId.package;
    //初始化第三方库/Makefile
    File('${Directory.current.path}${separator}pubspec.yaml').writeAsStringSync(
        readPubspec('${Directory.current.path}${separator}pubspec.yaml'),
        flush: true);
    File('${Directory.current.path}${separator}Makefile')
      ..createSync(recursive: true)
      ..writeAsStringSync(tpl.Tpl.makefileFile(package: package), flush: true);
    //删除main.dart, test
    File('${Directory.current.path}${separator}lib${separator}main.dart')
        .deleteSync();
    try {
      File('${Directory.current.path}${separator}test')
          .deleteSync(recursive: true);
    } catch (e) {}
    tpl.Tpl.buildCode.forEach((info) {
      var filePath =
          '${Directory.current.path}${separator}lib$separator${info.filePath}';
      File(filePath)
        ..createSync(recursive: true)
        ..writeAsStringSync(info.codeBuild(package: package), flush: true);
    });
    return null;
  }
}

class LibInfo {
  final String name;
  final String? version;
  final bool sdk;

  LibInfo({required this.name, this.version, this.sdk = false});
}

Builder projectBuilder(BuilderOptions options) =>
    LibraryBuilder(ProjectGenerator(), generatedExtension: ".project.dart");
